package cn.wolfcode.wolf2w.business.service.impl;

import cn.wolfcode.wolf2w.business.api.RemoteDestinationService;
import cn.wolfcode.wolf2w.business.api.RemoteNoteService;
import cn.wolfcode.wolf2w.business.api.RemoteStrategyService;
import cn.wolfcode.wolf2w.business.api.domain.Destination;
import cn.wolfcode.wolf2w.business.api.domain.Note;
import cn.wolfcode.wolf2w.business.api.domain.Strategy;
import cn.wolfcode.wolf2w.business.query.SearchQuery;
import cn.wolfcode.wolf2w.business.service.ISearchService;
import cn.wolfcode.wolf2w.common.core.constant.SecurityConstants;
import cn.wolfcode.wolf2w.member.api.RemoteUserInfoService;
import cn.wolfcode.wolf2w.member.api.domain.UserInfo;
import org.apache.commons.beanutils.BeanUtils;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Service
public class SearchServiceImpl implements ISearchService {
    @Autowired
    private ElasticsearchRestTemplate template;

    @Autowired
    private RemoteStrategyService remoteStrategyService;
    @Autowired
    private RemoteUserInfoService remoteUserInfoService;
    @Autowired
    private RemoteDestinationService remoteDestinationService;
    @Autowired
    private RemoteNoteService remoteNoteService;

    @Override
    public <T> Page<T> SearchQthHighLight(Class<T> clazz, Class<?> esClazz, SearchQuery qo, String... fields) throws InvocationTargetException, IllegalAccessException {
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.withQuery(
                QueryBuilders.multiMatchQuery(qo.getKeyword(), fields)
        );
        PageRequest pa = PageRequest.of(qo.getCurrentPage() - 1, qo.getPageSize());
        builder.withPageable(pa);
        HighlightBuilder.Field[] fs = new HighlightBuilder.Field[fields.length];
        String pre_tags = "<span style='color:red'>";
        String post_tags = "</span>";

        for (int i = 0; i < fs.length; i++) {
            HighlightBuilder.Field field = new HighlightBuilder.Field(fields[i]);
            field.preTags(pre_tags);
            field.postTags(post_tags);
            fs[i] = field;
        }
        builder.withHighlightFields(fs);

        SearchHits<?> hits = template.search(builder.build(), esClazz);
        long total = hits.getTotalHits();
        List<? extends SearchHit<?>> searchHits = hits.getSearchHits();

        List<T> list1 =  new ArrayList<>();
        for (SearchHit<?> hit : searchHits) {
            Long id = Long.valueOf(Objects.requireNonNull(hit.getId()));
            T t = null;
            if (clazz == Strategy.class) {
                t = (T) remoteStrategyService.getOne(id, SecurityConstants.INNER).getData();
            } else if (clazz == Note.class) {
                t = (T) remoteNoteService.getOne(id, SecurityConstants.INNER).getData();
            } else if (clazz == Destination.class) {
                t = (T) remoteDestinationService.getOne(id, "inner").getData();
            } else if (clazz == UserInfo.class) {
                t = (T) remoteUserInfoService.getOne(id, "inner").getData();
            }
            System.err.println(t.toString());
            Map<String, List<String>> highlightFields = hit.getHighlightFields();
            for (String key : highlightFields.keySet()) {
                List<String> list = highlightFields.get(key);

                StringBuilder stringBuilder = new StringBuilder();
                for (String s : list) {
                    stringBuilder.append(s);
                }
                //高亮列的内容
                String value = stringBuilder.toString();
                BeanUtils.setProperty(t,key,value);
            }
            //list是当前页的数据
            list1.add(t);
        }

        PageImpl<T> pageResult = new PageImpl<>(list1, pa, total);

        return pageResult;
    }
}
